package com.mgee.netty.server.netty;

import com.mgee.netty.server.pojo.NewChatUserInfo;
import com.mgee.netty.server.service.RoomService;
import com.mgee.netty.server.util.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.mgee.netty.server.constant.MessagingConst;
import com.mgee.netty.server.pojo.SessionCloseReason;
import com.mgee.netty.server.protobuf.ImProto.ImMsg;
import com.mgee.netty.server.util.ChannelUtils;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 通信服务处理器
 */
@Component
@Sharable
@Slf4j
public class ServerChannelHandlerAdapter extends ChannelInboundHandlerAdapter {
	/**
     * 注入请求分排器
     */
    @Autowired
    private MessageDispatcher messageDispatcher;
	
	@Autowired
	private SessionManager sessionManager;

	@Resource
	private RoomService roomService;

	/** 用来记录当前在线连接数。应该把它设计成线程安全的。  */
	//private AtomicInteger sessionCount = new AtomicInteger(0);
	
	@Override  
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {  
        super.handlerAdded(ctx); 
        
        if (!ChannelUtils.addChannelSession(ctx.channel(), new IoSession(ctx.channel()))) {
			ctx.channel().close();
			log.error("Duplicate session,IP=[{}]",ChannelUtils.getRemoteIp(ctx.channel()));
		}     

        //String server_ip = NetworkUtils.getRealIp();//获得本机IP
        // 缓存计数器加1
    }  
      
    @Override  
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {  
        super.handlerRemoved(ctx); 

        // 缓存计数器减1
        //String server_ip = NetworkUtils.getRealIp();//获得本机IP
        log.info(ctx.channel().id()+"离开了");  
    }
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    	
    	ImMsg gameMessage = (ImMsg)msg;
    	final Channel channel = ctx.channel();
		IoSession session = ChannelUtils.getSessionBy(channel);
		if(session.isHeartbeated()) {
			session.setHeartbeated(false);
		}
		
		String uid="";
		if(session.getUser() != null && StringUtils.isNotBlank(session.getUser().getUid())) {
			uid = session.getUser().getUid();
		}
		if(!MessagingConst.TYPE_UPOS_REQUEST.equals(gameMessage.getMsg().getTypeUrl())) {
			try {
				log.info("Inbound message is :" + JsonFormat.printer().usingTypeRegistry(SessionManager.typeRegistry).print(gameMessage.toBuilder())
						+ ", from user " + uid);
			} catch (InvalidProtocolBufferException e) {
				log.info("Inbound message is :" + gameMessage.toString());
			}
		}
		
		messageDispatcher.dispatch(gameMessage, session, ctx);
    }
     
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {  
        ctx.flush();  
    } 
    
    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)  
            throws Exception {  
    	
    	log.error("通信发生异常：", cause);
        ctx.close();   
    } 
    
    /**
	 * 一段时间未进行读写操作 回调
	 */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		String destroyUrl = "https://api-test.chimeta.com/v1/core/auth/tencent/destroySession";
		String projectId = "cap-4tfyjr51";

        /*心跳处理*/
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                /*读超时*/
                log.info("READER_IDLE read overtime，close session");
                final Channel channel = ctx.channel();
        		IoSession session = ChannelUtils.getSessionBy(channel);
				// 处理断开云桌面请求
				NewChatUserInfo newChatUserInfo = session.getNewChatUserInfo();
				if(newChatUserInfo != null && StringUtils.isNotBlank(newChatUserInfo.getUid())) {
					Map<String, Object> requestMap = new HashMap<>();
					requestMap.put("projectId", projectId);

					Map<String, Object> headerMap = new HashMap<>();
					headerMap.put("userid", newChatUserInfo.getUid());
					headerMap.put("Authorization", newChatUserInfo.getChimetaToken());

					RequestUtil.postJsonContent(destroyUrl, requestMap, headerMap);

					String roomNo = "chimeta";
					log.info("userEventTriggered newProcessExitRoom uid:{}, roomNo:{}", newChatUserInfo.getUid(), roomNo);
					roomService.newProcessExitRoom(newChatUserInfo.getUid(), roomNo);
				}

				/*
				 * if(messageDispatcher.sendHeartbeat(session) == false) { //如果心跳检测失败，则连接异常，主动断开
				 * session.setSessionCloseReason(SessionCloseReason.OVER_TIME); ctx.close(); };
				 */
        		
        		session.setSessionCloseReason(SessionCloseReason.OVER_TIME);
    			ctx.close();
                
            } else if (event.state() == IdleState.WRITER_IDLE) {
                /*写超时*/   
            	log.info("WRITER_IDLE 写超时");
            } else if (event.state() == IdleState.ALL_IDLE) {
                /*总超时*/
            	log.info("ALL_IDLE 总超时");
            }
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

//    	sessionManager.unregisterUserContext(ctx.channel());
    	sessionManager.disconnectAndDelayUnregister(ctx.channel(), 10);
    	log.info(ctx.channel().id() + "已断开！");
        // 这里加入玩家的掉线处理
        ctx.close();

    }

}